/*LICENSE_BEGIN
 * ******************************************************************
 * Copyright 2006 by the Dainamite Robocup-Team at the
 * DAI-Labor, TU-Berlin (www.dai-labor.de)
 * 
 * Members of Dainamite are:
 * Holger Endert
 * Robert Wetzker
 * Thomas Karbe
 * Axel Heßler
 * Philippe Bütter
 * Felix Brossmann
 * 
 * Licensed under the GNU GPL (General Public License) Free Software 
 * License, Version 2. You may use this file only in compliance with 
 * the License. You may obtain a copy of the License at:
 * 
 * http://www.fsf.org/licensing/licenses/gpl.txt
 * ******************************************************************
LICENSE_END*/
package robocup.component;

import robocup.component.geometry.Circle;
import robocup.component.geometry.Vektor;
import robocup.component.worldobjects.Flag;
import robocup.component.worldobjects.Line;

/**
 * All server params are remembered here. These params are received from the 
 * server after initialization of the agent, and are the same for all
 * players. Therefore a static class is used. These can also be found in the 
 * server.conf file, which is automatically created by the server in 
 * &lt;home&gt;/.rcssserver/ on first startup. <br><br>
 * Note that these values can't really be changed by the agent. If the listed
 * values are not equal to those sent by the server, the agent may expect a
 * different system behaviour and its calculations may subsequently be wrong. 
 * Hence changing these values should only be done after receiving the 
 * correct values from the server. 
 */
public class SConf {

	/**
	 * The SConf is implemented as singleton. Using the default constructor
	 * <code>new SConf()</code> creates a server configuration with the default
	 * values.
	 */
	private static SConf instance = new SConf();

	/**
	 * Retrieves a reference to the global SConf instance.
	 * 
	 * @return the server configuration
	 */
	public static SConf getInstance() {

		return SConf.instance;
	}

	/**
	 * This method sets a new server configuration.
	 * @param conf the new configuration
	 */
	public static void setInstance(SConf conf) {

		instance = conf;
	}

	/**
	 * <code>SConf</code> constructor Server specific constants, which have
	 * effect on various calculations.
	 */
	private SConf() {

		initFlagAreas();
	}

	
	/**
	 * The default position of the center of the opponents goal.
	 */
	public final Vektor GOAL_POS_OTHER = new Vektor(Vektor.XY, 0, 52.5);

	/**
	 * The default position of the left post of the opponents goal.
	 */
	public final Vektor GOAL_POST_LEFT_OTHER = new Vektor(Vektor.XY, -7, 52.5);

	/**
	 * The default position of the right post of the opponents goal.
	 */
	public final Vektor GOAL_POST_RIGHT_OTHER = new Vektor(Vektor.XY, +7, 52.5);

	/**
	 * The default position of the left post of the own goal.
	 */
	public final Vektor GOAL_POST_LEFT_OWN = new Vektor(Vektor.XY, -7, -52.5);

	/**
	 * The default position of the right post of the own goal.
	 */
	public final Vektor GOAL_POST_RIGHT_OWN = new Vektor(Vektor.XY, +7, -52.5);

	/**
	 * The default position of the center of the own goal.
	 */
	public final Vektor GOAL_POS_OWN = new Vektor(Vektor.XY, 0, -52.5);

	/**
	 * The default position of the left corner of the own side.
	 */
	public final Vektor CORNER_LEFT_OWN = new Vektor(Vektor.XY, -34, -52.5);

	/**
	 * The default position of the right corner of the own side.
	 */
	public final Vektor CORNER_RIGHT_OWN = new Vektor(Vektor.XY, 34, -52.5);

	/**
	 * The default position of the left corner of the opponents side.
	 */
	public final Vektor CORNER_LEFT_OTHER = new Vektor(Vektor.XY, -34, 52.5);

	/**
	 * The default position of the right corner of the opponents side.
	 */
	public final Vektor CORNER_RIGHT_OTHER = new Vektor(Vektor.XY, 34, 52.5);

	/**
	 * The offline coach (trainer) is allowed or not
	 */
	public boolean COACH = false;

	/**
	 * The maximal distance, in which a message from a player can be heared.
	 */
	public double AUDIO_CUT_DIST = 50.0;

	/**
	 * Backpasses are recognized by the referee (1.0) of not (0)
	 */
	public double BACK_PASSES = 1.0;

	/**
	 * The maximum ball acceleration factor (default 2.7)
	 */
	public double BALL_ACC_MAX = 2.7;

	/**
	 * The balls decau factor (default 0.94)
	 */
	public double BALL_DECAY = .94;

	/**
	 * The balls noise factor (default 0.05)
	 */
	public double BALL_RAND = .05;

	/**
	 * The balls size/radius (default 0.085m) 
	 */
	public double BALL_SIZE = .085;

	/**
	 * The maximal ball-speed (default 2.7)
	 */
	public double BALL_SPEED_MAX = 2.7;

	/**
	 * The balls weight (default 0.2)
	 */
	public double BALL_WEIGHT = .2;

	/**
	 * 
	 */
	public double CATCH_BAN_CYCLE = 5.0;

	/**
	 * The probability for the goalie to catch the ball (default 1)
	 */
	public double CATCH_PROBABILITY = 1.0;

	/**
	 * The length of the goalies catchable area (default 2.0m)
	 */
	public double CATCHABLE_AREA_L = 2.0;

	/**
	 * The width of the goalies catchable area (default 1.0m)
	 */
	public double CATCHABLE_AREA_W = 1.0;

	/**
	 * The maximum allowed angle of the goalie to catch the ball (default 180)
	 */
	public double CATCH_MAXMOMENT = 180.0;

	/**
	 * The minimum allowed angle of the goalie to catch the ball (default -180)
	 */
	public double CATCH_MINMOMENT = -180.0;

	/**
	 * 
	 */
	public double CKICK_MARGIN = 1.0;

	/**
	 * The amount of cycles, which must be waited before the next clang message
	 * is accepted by the server (freeform messages have an own window)
	 * (default 300)
	 */
	public int CLANG_WIN_SIZE = 300;

	/**
	 * The time in cycles, after which the ball is dropped, if no action happen
	 * in standard playmodes (default 200)
	 */
	public double DROP_BALL_TIME = 200.0;

	/**
	 * Effort decrease step, if the stamina is lower than STAMINA_MAX * 
	 * EFFORT_DEC_THR (default 0.005)
	 */
	public double EFFORT_DEC = .005;

	/**
	 * The threshold factor for the stamina, which indicates a decrease of the 
	 * players effort, if stamina is lower than STAMINA_MAX * EFFORT_DEC_THR.
	 * (default 0.3)
	 */
	public double EFFORT_DEC_THR = .3;

	/**
	 * Effort increase step, if the stamina is lower than STAMINA_MAX * 
	 * EFFORT_INC_THR (default 0.01).
	 */
	public double EFFORT_INC = .01;

	/**
	 * The threshold factor for the stamina, which indicates an increase of the 
	 * players effort, if stamina is lower than STAMINA_MAX * EFFORT_INC_THR.
	 * (default 0.6).
	 */
	public double EFFORT_INC_THR = .6;

	/**
	 * The default effort value (1.0)
	 */
	public double EFFORT_INIT = 1.0;

	/**
	 * If set to 1, offside is recognized by the referee after 
	 * kickoff (default 1)
	 */
	public double FORBID_KICK_OFF_OFFSIDE = 1.0;

	/**
	 * If set to 1, free-kick-fauls are recognized by the referee (e.g. the
	 * free kick is intercepted by the executing agent itself). 
	 * (default 1)
	 */
	public double FREE_KICK_FAULTS = 1.0;

	/**
	 * The time in cycles, which is waited before a freeform message
	 * is forwarded to the agents (default 20)
	 */
	public int FREEFORM_SEND_PERIOD = 20;

	/**
	 * The time in cycles, which is waited before a new freeform message
	 * is accepted by the server (default 600)
	 */
	public int FREEFORM_WAIT_PERIOD = 600;

	/**
	 * The width of a goal (default 14.02)
	 */
	public double GOAL_WIDTH = 14.02;

	/**
	 * The maximum number of moves allowed to execute by the goalie after 
	 * catching a ball (default 2)
	 */
	public int GOALIE_MAX_MOVES = 2;

	/**
	 * The half-time length in cycles (default 30, in official 
	 * tournaments 300)
	 */
	public double HALF_TIME = 30.0;

	/**
	 * The step by which the actual allowed number of messages per team is
	 * decreased on receivement (default 1)
	 */
	public double HEAR_DECAY = 1.0;

	/**
	 * The step by which the actual allowed number of messages is increased
	 * each cycle (default 1) 
	 */
	public double HEAR_INC = 1.0;

	/**
	 * The maximum number of messages allowed to receive per team each cycle.
	 * This means, that a player can hear at most two times HEAR_MAX messages
	 * per cycle. (default 1)
	 */
	public double HEAR_MAX = 1.0;

	/**
	 * The time in cycles, which is waited, before the game is set to play-mode
	 * kick-off (default 100)
	 */
	public double KICK_OFF_WAIT = 100.0;

	/**
	 * The kick-power rate for a player (default 0.027), which 
	 * determines the acceleration of the ball.
	 */
	public double KICK_POWER_RATE = .027;


	/**
	 * (default 0.1)
	 */
	public double MARGIN_NOISE = .1;

	/**
	 * 
	 */
	public double MAX_GOAL_KICKS = 3.0;

	/**
	 * The maximum angle an agent can set to a turn command (default 180)
	 */
	public double MAXMOMENT = 180.0;

	/**
	 * The maximum neck-angle (default 90)
	 */
	public double MAXNECKANG = 90.0;

	/**
	 * The maximum angle an agent can set to a turnneck command (default 180)
	 */
	public double MAXNECKMOMENT = 180.0;

	/**
	 * The maximum dash-power an agent can use (default 100)
	 */
	public double MAXPOWER = 100.0;

	/**
	 * The minimum angle an agent can set to a turn command (default -180)
	 */
	public double MINMOMENT = -180.0;

	/**
	 * The minimum neck-angle (default 90)
	 */
	public double MINNECKANG = -90.0;

	/**
	 * The minimum angle an agent can set to a turnneck command (default -180)
	 */
	public double MINNECKMOMENT = -180.0;

	/**
	 * The minimum dash-power an agent can use (default -100). Note that 
	 * negative values indicate backward dashing.
	 */
	public double MINPOWER = -100.0;

	/**
	 * The maximum acceleration factor for a player (default 1)
	 */
	public double PLAYER_ACCEL_MAX = 1.0;


	/**
	 * The players random movement noise (default 0.1)
	 */
	public double PLAYER_RAND = 0.1;

	/**
	 * The players weight (default 60)
	 */
	public double PLAYER_WEIGHT = 60.0;

	/**
	 * The number of cycles a point-to action must last at minimum (default 5)
	 */
	public int POINT_TO_BAN = 5;

	/**
	 * The number of cycles a point-to action last, if not renewed (default 20)
	 */
	public int POINT_TO_DURATION = 20;

	/**
	 * The step by which the recovery-value is decreased, if the corresponding 
	 * stamina threshold is underrun. Note that recovery will not increase
	 * with high stamina. (default 0.002)
	 */
	public double RECOVER_DEC = .002;

	/**
	 * The factor for the stamina value, which determines the recovery-decrease
	 * threshold (default 0.3)
	 */
	public double RECOVER_DEC_THR = .3;

	/**
	 * The value, which is set to recovery on reinit (after half-time)
	 * (default 1)
	 */
	public double RECOVER_INIT = 1.0;

	/**
	 * The maximum recovery value (default 1)
	 */
	public double RECOVER_MAX = 1.0;

	/**
	 * The minimum recovery value (default 0.5)
	 */
	public double RECOVER_MIN = 0.5;

	/**
	 * upper limit of the number of online coach's message (default 128)
	 */
	public int SAY_COACH_COUNT_MAX = 128;

	/**
	 * The number of allowed characters in a freeform message (default 128)
	 */
	public int SAY_COACH_MSG_SIZE = 128;

	/**
	 * The number of allowed characters in a player say action (default 10)
	 */
	public int SAY_MSG_SIZE = 10;

	/**
	 * The interval in milliseconds, after which a new sensebody info is send
	 * by the server (default 100)
	 */
	public int SENSE_BODY_STEP = 100;


	/**
	 * The maximum stamina value of a player (default 4000)
	 */
	public double STAMINA_MAX = 4000.0;

	/**
	 * The velocity, by which the ball is set to speed 0 (default 0.01)
	 */
	public double STOPPED_BALL_VEL = 0.01;

	/**
	 * The maximum distance a player can tackle backwards (default 0.5)
	 */
	public double TACKLE_BACK_DIST = 0.5;

	/**
	 * The number of cycles an player is disabled after tackling (default 10)
	 */
	public int TACKLE_CYCLES = 10;

	/**
	 * The maximum distance a player can tackle forward (default 2.0)
	 */
	public double TACKLE_DIST = 2.0;

	/**
	 * A factor for determining the tackle-success probability. Depends on the
	 * distance to the ball (default 6.0) Note, that this value is an exponent! 
	 */
	public double TACKLE_EXPONENT = 6.0;

	/**
	 * The tackle power rate, which determines the acceleration of a tackled
	 * ball (default 0.027)
	 */
	public double TACKLE_POWER_RATE = 0.027;

	/**
	 * The width, in which tackling generally is allowed. Note that for distant
	 * balls, the probability of successful tacklings is null, although the
	 * ball is within the tackle area. (default 1.0m)
	 */
	public double TACKLE_WIDTH = 1.0;

	/**
	 * The basic visible angle (default 90).
	 */
	public double VISIBLE_ANGLE = 90.0;

	/**
	 * This distance in meter, in which a player can "sense" objects (default
	 * 3.0)
	 */
	public double VISIBLE_DISTANCE = 3.0;

	/**
	 * Determines if offside is recognized by the referee 
	 * (default 1|true)
	 */
	public int USE_OFFSIDE = 1;

	/**
	 * The length of one field-half (default 52.5)
	 */
	public double half_length = 52.5; // Half

	/**
	 * The width of one field-half (default 34)
	 */
	public double half_width = 34; // Half

	/**
	 * The width of a half goal (default 7.01)
	 */
	public double half_goal_width = 7.01; // Half

	/**
	 * The length of the penalty area (default 16.5)
	 */
	public double penalty_length = 16.5; // Penalty

	/**
	 * The width of the penalty area (default 20.175)
	 */
	public double half_penalty_width = 20.175; // Half

    /**
     * Sirka nebezpecnej zony pred branou
     */
    public double dangerArea_width = half_penalty_width +5;

    /**
	 * Dlzka nebezpecnej zony pred branou
	 */
	public double dangerArea_length = penalty_length +5;

	/**
	 * The distance from the field border to the physical
	 * field boundary (default 5)
	 */
	private double boundary_distance = 5.0; // Boundary

	/**
	 * Marker for horizontal width 10m (flags use them)
	 */
	private double half_horizontal_10_width = 10.0; // Half

	/**
	 * Marker for horizontal width 20m (flags use them)
	 */
	private double half_horizontal_20_width = 20.0; // Half

	/**
	 * Marker for horizontal width 30m (flags use them)
	 */
	private double half_horizontal_30_width = 30.0; // Half

	/**
	 * Marker for vertical length 10m (flags use them)
	 */
	private double half_vertical_10_length = 10.0; // Half

	/**
	 * Marker for vertical length 20m (flags use them)
	 */
	private double half_vertical_20_length = 20.0; // Half

	/**
	 * Marker for vertical length 30m (flags use them)
	 */
	private double half_vertical_30_length = 30.0; // Half

	/**
	 * Marker for vertical length 40m (flags use them)
	 */
	private double half_vertical_40_length = 40.0; // Half

	/**
	 * Marker for vertical length 50m (flags use them)
	 */
	private double half_vertical_50_length = 50.0; // Half

	/**
	 * All known flags. Note that these flags refer to the servers
	 * coordinate space and hence must not be turned. <br>
	 * <ol start=0>
	 * 	<li>CENTER = (flag c)
	 *  <li>CENTER_LEFT = (flag c t)
	 *  <li>CENTER_RIGHT = (flag c b)
	 *  <li>PENALTY_CENTER_TOP = (flag p r c)
	 *  <li>PENALTY_LEFT_TOP = (flag p r t)
	 *  <li>PENALTY_RIGHT_TOP = (flag p r b)
	 *  <li>PENALTY_CENTER_BOTTOM = (flag p l c)
	 *  <li>PENALTY_LEFT_BOTTOM = (flag p l t)
	 *  <li>PENALTY_RIGHT_BOTTOM = (flag p l b)
	 *  <li>GOAL_TOP = (goal r)
	 *  <li>GOAL_LEFT_TOP = (flag g r t)
	 *  <li>GOAL_RIGHT_TOP = (flag g r b)
	 *  <li>GOAL_BOTTOM = (goal l)
	 *  <li>GOAL_LEFT_BOTTOM = (flag g l t)
	 *  <li>GOAL_RIGHT_BOTTOM = (flag b l b) isn't it (flag g l b)?
	 *  <li>CORNER_LEFT_TOP = (flag r t)
	 *  <li>CORNER_RIGHT_TOP = (flag r b)
	 *  <li>CORNER_LEFT_BOTTOM = (flag l t)
	 *  <li>CORNER_RIGHT_BOTTOM = (flag l b)
	 *  <li>BOUND_TOP = (flag r 0)
	 *  <li>BOUND_TOP_LEFT_10 = (flag r t 10)
	 *  <li>BOUND_TOP_RIGHT_10 = (flag r b 10)
	 *  <li>BOUND_TOP_LEFT_20 = (flag r t 20)
	 *  <li>BOUND_TOP_RIGHT_20 = (flag r b 20)
	 *  <li>BOUND_TOP_LEFT_30 = (flag r t 30)
	 *  <li>BOUND_TOP_RIGHT_30 = (flag r b 30)
	 *  <li>BOUND_BOTTOM = (flag l 0)
	 *  <li>BOUND_BOTTOM_LEFT_10 = (flag l t 10)
	 *  <li>BOUND_BOTTOM_RIGHT_10 = (flag l b 10)
	 *  <li>BOUND_BOTTOM_LEFT_20 = (flag l t 20)
	 *  <li>BOUND_BOTTOM_RIGHT_20 = (flag l b 20)
	 *  <li>BOUND_BOTTOM_LEFT_30 = (flag l t 30)
	 *  <li>BOUND_BOTTOM_RIGHT_30 = (flag l b 30)
	 *  <li>BOUND_LEFT = (flag t 0)
	 *  <li>BOUND_LEFT_BOTTOM_10 = (flag t l 10)
	 *  <li>BOUND_LEFT_TOP_10 = (flag t r 10)
	 *  <li>BOUND_LEFT_BOTTOM_20 = (flag t l 20)
	 *  <li>BOUND_LEFT_TOP_20 = (flag t r 20)
	 *  <li>BOUND_LEFT_BOTTOM_30 = (flag t l 30)
	 *  <li>BOUND_LEFT_TOP_30 = (flag t r 30)
	 *  <li>BOUND_LEFT_BOTTOM_40 = (flag t l 40)
	 *  <li>BOUND_LEFT_TOP_40 = (flag t r 40)
	 *  <li>BOUND_LEFT_BOTTOM_50 = (flag t l 50)
	 *  <li>BOUND_LEFT_TOP_50 = (flag t r 50)
	 *  <li>BOUND_RIGHT = (flag b 0)
	 *  <li>BOUND_RIGHT_BOTTOM_10 = (flag b l 10)
	 *  <li>BOUND_RIGHT_TOP_10 = (flag b r 10)
	 *  <li>BOUND_RIGHT_BOTTOM_20 = (flag b l 20)
	 *  <li>BOUND_RIGHT_TOP_20 = (flag b r 20)
	 *  <li>BOUND_RIGHT_BOTTOM_30 = (flag b l 30)
	 *  <li>BOUND_RIGHT_TOP_30 = (flag b r 30)
	 *  <li>BOUND_RIGHT_BOTTOM_40 = (flag b l 40)
	 *  <li>BOUND_RIGHT_TOP_40 = (flag b r 40)
	 *  <li>BOUND_RIGHT_BOTTOM_50 = (flag b l 50)
	 *  <li>BOUND_RIGHT_TOP_50 = (flag b r 50)
	 * </ol>
	 */
	private final Flag[] flags = {
			// CENTER = (flag c)
			new Flag(-1, 5, new Vektor(Vektor.XY, 0.0, 0.0)),
			// CENTER_LEFT = (flag c t)
			new Flag(-1, 51, new Vektor(Vektor.XY, -this.half_width, 0.0)),
			// CENTER_RIGHT = (flag c b)
			new Flag(-1, 52, new Vektor(Vektor.XY, this.half_width, 0.0)),

			// PENALTY_CENTER_TOP = (flag p r c)
			new Flag(-1, 745, new Vektor(Vektor.XY, 0.0, this.half_length
					- this.penalty_length)),
			// PENALTY_LEFT_TOP = (flag p r t)
			new Flag(-1, 741, new Vektor(Vektor.XY, -this.half_penalty_width,
					this.half_length - this.penalty_length)),
			// PENALTY_RIGHT_TOP = (flag p r b)
			new Flag(-1, 742, new Vektor(Vektor.XY, this.half_penalty_width,
					this.half_length - this.penalty_length)),
			// PENALTY_CENTER_BOTTOM = (flag p l c)
			new Flag(-1, 735, new Vektor(Vektor.XY, 0.0, -this.half_length
					+ this.penalty_length)),
			// PENALTY_LEFT_BOTTOM = (flag p l t)
			new Flag(-1, 731, new Vektor(Vektor.XY, -this.half_penalty_width,
					-this.half_length + this.penalty_length)),
			// PENALTY_RIGHT_BOTTOM = (flag p l b)
			new Flag(-1, 732, new Vektor(Vektor.XY, this.half_penalty_width,
					-this.half_length + this.penalty_length)),

			// GOAL_TOP = (goal r)
			new Flag(-1, 640, new Vektor(Vektor.XY, 0.0, this.half_length)),
			// GOAL_LEFT_TOP = (flag g r t)
			new Flag(-1, 641, new Vektor(Vektor.XY, -this.half_goal_width,
					this.half_length)),
			// GOAL_RIGHT_TOP = (flag g r b)
			new Flag(-1, 642, new Vektor(Vektor.XY, this.half_goal_width,
					this.half_length)),
			// GOAL_BOTTOM = (goal l)
			new Flag(-1, 630, new Vektor(Vektor.XY, 0.0, -this.half_length)),
			// GOAL_LEFT_BOTTOM = (flag g l t)
			new Flag(-1, 631, new Vektor(Vektor.XY, -this.half_goal_width,
					-this.half_length)),
			// GOAL_RIGHT_BOTTOM = (flag b l b) isn't it (flag g l b)?
			new Flag(-1, 632, new Vektor(Vektor.XY, this.half_goal_width,
					-this.half_length)),

			// CORNER_LEFT_TOP = (flag r t)
			new Flag(-1, 41, new Vektor(Vektor.XY, -this.half_width,
					this.half_length)),
			// CORNER_RIGHT_TOP = (flag r b)
			new Flag(-1, 42, new Vektor(Vektor.XY, this.half_width,
					this.half_length)),
			// CORNER_LEFT_BOTTOM = (flag l t)
			new Flag(-1, 31, new Vektor(Vektor.XY, -this.half_width,
					-this.half_length)),
			// CORNER_RIGHT_BOTTOM = (flag l b)
			new Flag(-1, 32, new Vektor(Vektor.XY, this.half_width,
					-this.half_length)),

			// BOUND_TOP = (flag r 0)
			new Flag(-1, 40, new Vektor(Vektor.XY, 0.0, this.half_length
					+ this.boundary_distance)),
			// BOUND_TOP_LEFT_10 = (flag r t 10)
			new Flag(-1, 141, new Vektor(Vektor.XY,
					-this.half_horizontal_10_width, this.half_length
							+ this.boundary_distance)),
			// BOUND_TOP_RIGHT_10 = (flag r b 10)
			new Flag(-1, 142, new Vektor(Vektor.XY,
					this.half_horizontal_10_width, this.half_length
							+ this.boundary_distance)),
			// BOUND_TOP_LEFT_20 = (flag r t 20)
			new Flag(-1, 241, new Vektor(Vektor.XY,
					-this.half_horizontal_20_width, this.half_length
							+ this.boundary_distance)),
			// BOUND_TOP_RIGHT_20 = (flag r b 20)
			new Flag(-1, 242, new Vektor(Vektor.XY,
					this.half_horizontal_20_width, this.half_length
							+ this.boundary_distance)),
			// BOUND_TOP_LEFT_30 = (flag r t 30)
			new Flag(-1, 341, new Vektor(Vektor.XY,
					-this.half_horizontal_30_width, this.half_length
							+ this.boundary_distance)),
			// BOUND_TOP_RIGHT_30 = (flag r b 30)
			new Flag(-1, 342, new Vektor(Vektor.XY,
					this.half_horizontal_30_width, this.half_length
							+ this.boundary_distance)),

			// BOUND_BOTTOM = (flag l 0)
			new Flag(-1, 30, new Vektor(Vektor.XY, 0.0, -this.half_length
					- this.boundary_distance)),
			// BOUND_BOTTOM_LEFT_10 = (flag l t 10)
			new Flag(-1, 131, new Vektor(Vektor.XY,
					-this.half_horizontal_10_width, -this.half_length
							- this.boundary_distance)),
			// BOUND_BOTTOM_RIGHT_10 = (flag l b 10)
			new Flag(-1, 132, new Vektor(Vektor.XY,
					this.half_horizontal_10_width, -this.half_length
							- this.boundary_distance)),
			// BOUND_BOTTOM_LEFT_20 = (flag l t 20)
			new Flag(-1, 231, new Vektor(Vektor.XY,
					-this.half_horizontal_20_width, -this.half_length
							- this.boundary_distance)),
			// BOUND_BOTTOM_RIGHT_20 = (flag l b 20)
			new Flag(-1, 232, new Vektor(Vektor.XY,
					this.half_horizontal_20_width, -this.half_length
							- this.boundary_distance)),
			// BOUND_BOTTOM_LEFT_30 = (flag l t 30)
			new Flag(-1, 331, new Vektor(Vektor.XY,
					-this.half_horizontal_30_width, -this.half_length
							- this.boundary_distance)),
			// BOUND_BOTTOM_RIGHT_30 = (flag l b 30)
			new Flag(-1, 332, new Vektor(Vektor.XY,
					this.half_horizontal_30_width, -this.half_length
							- this.boundary_distance)),

			// BOUND_LEFT = (flag t 0)
			new Flag(-1, 10, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, 0.0)),
			// BOUND_LEFT_BOTTOM_10 = (flag t l 10)
			new Flag(-1, 113, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, -this.half_vertical_10_length)),
			// BOUND_LEFT_TOP_10 = (flag t r 10)
			new Flag(-1, 114, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, this.half_vertical_10_length)),
			// BOUND_LEFT_BOTTOM_20 = (flag t l 20)
			new Flag(-1, 213, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, -this.half_vertical_20_length)),
			// BOUND_LEFT_TOP_20 = (flag t r 20)
			new Flag(-1, 214, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, this.half_vertical_20_length)),
			// BOUND_LEFT_BOTTOM_30 = (flag t l 30)
			new Flag(-1, 313, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, -this.half_vertical_30_length)),
			// BOUND_LEFT_TOP_30 = (flag t r 30)
			new Flag(-1, 314, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, this.half_vertical_30_length)),
			// BOUND_LEFT_BOTTOM_40 = (flag t l 40)
			new Flag(-1, 413, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, -this.half_vertical_40_length)),
			// BOUND_LEFT_TOP_40 = (flag t r 40)
			new Flag(-1, 414, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, this.half_vertical_40_length)),
			// BOUND_LEFT_BOTTOM_50 = (flag t l 50)
			new Flag(-1, 513, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, -this.half_vertical_50_length)),
			// BOUND_LEFT_TOP_50 = (flag t r 50)
			new Flag(-1, 514, new Vektor(Vektor.XY, -this.half_width
					- this.boundary_distance, this.half_vertical_50_length)),

			// BOUND_RIGHT = (flag b 0)
			new Flag(-1, 20, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, 0.0)),
			// BOUND_RIGHT_BOTTOM_10 = (flag b l 10)
			new Flag(-1, 123, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, -this.half_vertical_10_length)),
			// BOUND_RIGHT_TOP_10 = (flag b r 10)
			new Flag(-1, 124, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, this.half_vertical_10_length)),
			// BOUND_RIGHT_BOTTOM_20 = (flag b l 20)
			new Flag(-1, 223, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, -this.half_vertical_20_length)),
			// BOUND_RIGHT_TOP_20 = (flag b r 20)
			new Flag(-1, 224, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, this.half_vertical_20_length)),
			// BOUND_RIGHT_BOTTOM_30 = (flag b l 30)
			new Flag(-1, 323, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, -this.half_vertical_30_length)),
			// BOUND_RIGHT_TOP_30 = (flag b r 30)
			new Flag(-1, 324, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, this.half_vertical_30_length)),
			// BOUND_RIGHT_BOTTOM_40 = (flag b l 40)
			new Flag(-1, 423, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, -this.half_vertical_40_length)),
			// BOUND_RIGHT_TOP_40 = (flag b r 40)
			new Flag(-1, 424, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, this.half_vertical_40_length)),
			// BOUND_RIGHT_BOTTOM_50 = (flag b l 50)
			new Flag(-1, 523, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, -this.half_vertical_50_length)),
			// BOUND_RIGHT_TOP_50 = (flag b r 50)
			new Flag(-1, 524, new Vektor(Vektor.XY, this.half_width
					+ this.boundary_distance, this.half_vertical_50_length)) };


	/**
	 * All known lines. Note that these refer to the servers coordinate
	 * space and hence must not be turned.
	 * <ol start=0>
	 * 	<li>LINE_CENTER = (line c)
	 * 	<li>LINE_BOTTOM = (line l)
	 *  <li>LINE_TOP = (line r)
	 *  <li>LINE_LEFT = (line t)
	 *  <li>LINE_RIGHT = (line b)
	 * </ol>
	 * 
	 */
	private final Line[] lines = {

			// LINE_CENTER = (line c)
			new Line(-1, 2000, new Vektor(Vektor.XY, -this.half_width, 0.0),
					new Vektor(Vektor.XY, this.half_width, 0.0)),

			// LINE_BOTTOM = (line l)
			new Line(-1, 2001, new Vektor(Vektor.XY, -this.half_width,
					-this.half_length), new Vektor(Vektor.XY, this.half_width,
					-this.half_length)),

			// LINE_TOP = (line r)
			new Line(-1, 2002, new Vektor(Vektor.XY, -this.half_width,
					this.half_length), new Vektor(Vektor.XY, this.half_width,
					this.half_length)),

			// LINE_LEFT = (line t)
			new Line(-1, 2003, new Vektor(Vektor.XY, -this.half_width,
					this.half_length), new Vektor(Vektor.XY, -this.half_width,
					-this.half_length)),

			// LINE_RIGHT = (line b)
			new Line(-1, 2004, new Vektor(Vektor.XY, this.half_width,
					this.half_length), new Vektor(Vektor.XY, this.half_width,
					-this.half_length)) }; // end

	
	/**
	 * An array of circles, whereas in each center is one of the flags
	 * located. These are used to retrieve a certain flag if perceived
	 * with noise.
	 */
	private Circle[] flagArea;

	/**
	 * <code>initFlagAreas</code> creates an array of circles arouns each
	 * flag, with a radius of <code>DAInamiteConstants.WM_FLAG_RADIUS</code>
	 */
	private void initFlagAreas() {

		this.flagArea = new Circle[this.flags.length];
		Vektor flagPos;
		for (int i = 0; i < this.flags.length; i++) {
			flagPos = this.flags[i].getPosition();
			this.flagArea[i] = new Circle(flagPos,
					DAInamiteConstants.WM_FLAG_RADIUS);
		}
	}

	/**
	 * <code>getFlag</code> returns a flag near the <code>position</code>.
	 * @param position
	 * @return The flag which is nearest to the given position,
	 * if this is within the corresponding <code>flagArea</code>. Else <code>null</code>
	 * is returned. 
	 */
	public final Flag getFlag(Vektor position) {

		for (int i = 0; i < this.flagArea.length; i++) {
			if (this.flagArea[i].liesWithinCircle(position)) {
				return this.flags[i];
			}
		}
		return null;
	}

	/**
	 * Returns the pertinent Flag to the id.
	 * 
	 * @param id
	 *            of the flag
	 * @return Flag if the id was correct, else null.
	 */
	public Flag getFlag(int id) {

		Flag temp = null;
		for (int i = 0; i < this.flags.length; i++)
			if (this.flags[i].getId() == id) {
				temp = this.flags[i];
				break;
			} // end of if

		return temp;
	} // end of method getFlag(int id)

	/**
	 * Returns the pertinent Line to the id.
	 * 
	 * @param id
	 *            of the line
	 * @return Line if the id was correct, else null.
	 */
	public Line getLine(int id) {

		id -= 2000;
		if (id < 0 || this.lines.length <= id)
			return null;

		return this.lines[id];
	}

}
